package com.macro.mall.portal.service.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alipay.api.domain.*;
import com.macro.mall.mapper.PmsProductEvaluationTagsMapper;
import com.macro.mall.mapper.PmsSkuStockMapper;
import com.macro.mall.model.PmsProductEvaluationTags;
import com.macro.mall.model.PmsSkuStock;
import com.macro.mall.model.UmsMember;
import com.macro.mall.portal.dao.UmsCommentDao;
import com.macro.mall.portal.dao.UmsTagsCommentDao;
import com.macro.mall.portal.dao.UmsViewCommentDao;
import com.macro.mall.portal.domain.*;
import com.macro.mall.portal.service.UmsCommentService;
import com.macro.mall.portal.service.UmsMemberService;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.rmi.server.ServerCloneException;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;


/**
 * @Author：Minxiao-Hao
 * @Description: 评论接口实现类
 * @name：UmsCommentServiceImpl
 * @Date：2024/10/26 13:50
 */
@Service
@Slf4j
public class UmsCommentServiceImpl implements UmsCommentService {
    @Autowired
    private UmsCommentDao umsCommentDao;
    @Autowired
    private UmsViewCommentDao umsViewCommentDao;
    @Autowired
    private UmsTagsCommentDao umsTagsCommentDao;
    @Autowired
    private UmsMemberService umsMemberService;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private PmsSkuStockMapper pmsSkuStockMapper;
    @Autowired
    private PmsProductEvaluationTagsMapper pmsProductEvaluationTagsMapper;
    /**
     * 添加商品评论接口
     * @param commentDto 评论请求对象
     * @return 成功条数
     */
    @Override
    @Transactional
    public void addComment(CommentDto commentDto) {


        // 检查评论请求对象是否为空
        if (commentDto == null || commentDto.getUmsComment() == null) {
            throw new IllegalArgumentException("评论请求对象或评论内容不能为空");
        }

//        for (int i = 0; i < 10; i++) {    //测试异步执行速度
            UmsComment umsComment = commentDto.getUmsComment();
            UmsMember currentMember = umsMemberService.getCurrentMember();

            // 设置评论创建者和时间
            umsComment.setCreateBy(currentMember.getUsername());
            umsComment.setCreateTime(new Date());

            try {
                // 添加评论并获取返回的评论ID
                Integer commentId = umsCommentDao.addComment(umsComment);
                if (commentId == null) {
                    throw new ServerCloneException("评价未添加上去");
                }
                UmsCommentServiceImpl bean = applicationContext.getBean(UmsCommentServiceImpl.class);
                // 添加视图
                bean.addView(commentDto, commentId);
                // 添加标签
                bean.addTags(commentDto, commentId);
            } catch (Exception e) {
                // 记录日志并抛出异常
                log.debug("添加评论失败,错误信息为:{}", e.getMessage());
                throw new RuntimeException("添加评论时发生错误");
            }
//        }
    }


    /**
     * 添加标签
     * @param commentDto 请求对象
     * @param commentId 评论id
     */
    @Async("commentAddThreadPool")   //异步
    void addTags(CommentDto commentDto, Integer commentId) throws InterruptedException {
        long startTime = System.currentTimeMillis();
        // 添加标签
        List<String> tagsIds = commentDto.getTagsIds();
        if (CollectionUtils.isNotEmpty(tagsIds)) {
            umsTagsCommentDao.addTags(commentId, tagsIds);
        }
        Thread.sleep(1000);
        //记录结束时间并计算耗时
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        log.info("添加视图的耗时: {} 毫秒", duration);
    }

    /**
     * 添加视图
     * @param commentDto 请求对象
     * @param commentId 评论id
     */
    @Async("commentAddThreadPool")  //异步
    void addView(CommentDto commentDto, Integer commentId) throws InterruptedException {
        long startTime = System.currentTimeMillis();
        // 添加评论图片
        List<UmsView> umsViewsData = commentDto.getUmsViewsData();
        if (CollectionUtils.isNotEmpty(umsViewsData)) {
            umsViewCommentDao.addView(commentId, umsViewsData);
        }
        Thread.sleep(1000);
        // 记录结束时间并计算耗时
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        log.info("添加视图的耗时: {} 毫秒", duration);
    }

    /**
     * 评论列表接口
     * @param productId 商品ID
     * @return 评论列表
     */
    @Override
    public List<CommentDetail> list(Long productId) {
        // 检查商品ID是否为空
        if (productId == null) {
            throw new RuntimeException("商品ID不能为空");
        }

        // 查询所有的评论信息
        List<CommentInfo> commentInfos = umsCommentDao.getList();
        //通过反射获取本类实例
        UmsCommentServiceImpl bean = applicationContext.getBean(UmsCommentServiceImpl.class);
        try {

            Future<List<CommentInfo>> commentInfos1 = bean.getCommentInfos(productId, commentInfos);
            // 获取评论信息
            List<CommentInfo> filteredCommentInfos = commentInfos1.get();

            // 获取评论ID列表
            List<Integer> allCommentIds = filteredCommentInfos.stream()
                    .map(CommentInfo::getId)
                    .collect(Collectors.toList());
            //对评论id进行判空
            if (!CollectionUtils.isEmpty(allCommentIds)) {
                // 根据所有评论ID查询所有标签，并以评论ID进行分组
                List<UmsTagsComment> umsTagsComments = umsTagsCommentDao.findByCommentIds(allCommentIds);
                Map<Integer, List<Integer>> commentTagsMap = umsTagsComments.stream()
                        .collect(Collectors.groupingBy(UmsTagsComment::getCommentId,
                                Collectors.mapping(UmsTagsComment::getTagsId, Collectors.toList())));

                Future<Map<Integer, String>> integerStringMap = bean.getIntegerStringMap(commentTagsMap);
                //获取评论id和名称
                Map<Integer, String> tagNameMap = integerStringMap.get();

                Future<Map<Integer, List<UmsViewComment>>> integerListMap = getIntegerListMap(allCommentIds);
                //获取评论id和视图对象
                Map<Integer, List<UmsViewComment>> commentViewMap = integerListMap.get();

                // 填充标签名称和视图对象
                filteredCommentInfos.forEach(commentInfo -> {
                    // 获取标签名称列表
                    List<Integer> tagIds = commentTagsMap.get(commentInfo.getId());
                    List<String> tagNames = Optional.ofNullable(tagIds)
                            .orElse(Collections.emptyList()).stream()
                            .map(tagNameMap::get)
                            .collect(Collectors.toList());
                    commentInfo.setTagsNames(tagNames);

                    // 获取视图对象列表
                    commentInfo.setUmsViewComments(commentViewMap.get(commentInfo.getId()));
                });

                // 获取商品评价的总数量和好评率
                CommentDetail detail = new CommentDetail();
                detail.setGoodRate(umsCommentDao.goodRate(productId));
                detail.setCommentCount(umsCommentDao.commentCount(productId));
                detail.setCommentInfos(filteredCommentInfos);

                // 返回包含评论详情的列表
                return Collections.singletonList(detail);
            }
            return null;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 获取评论视图对象
     * @param allCommentIds 所有评论ID
     * @return 视图对象
     */
    @NotNull
    @Async("commentListThreadPool")
     Future<Map<Integer, List<UmsViewComment>>> getIntegerListMap(List<Integer> allCommentIds) {
        // 根据评论ID查询所有的视图信息
        List<UmsViewComment> umsViewCommentList = umsViewCommentDao.findByCommentIds(allCommentIds);
        Map<Integer, List<UmsViewComment>> commentViewMap = umsViewCommentList.stream()
                .collect(Collectors.groupingBy(UmsViewComment::getCommentId));
        return  new AsyncResult<>(commentViewMap);
    }

    /**
     * 获取标签名称
     * @param commentTagsMap 评论标签映射
     * @return 标签名称映射
     */

    @NotNull
    @Async("commentListThreadPool")
    Future<Map<Integer, String>> getIntegerStringMap(Map<Integer, List<Integer>> commentTagsMap) {
        // 查询标签名称，并封装成Map，以便快速查找
        List<Integer> allTagIds = commentTagsMap.values().stream()
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());

        Map<Integer, String> tagNameMap = pmsProductEvaluationTagsMapper.findByTagsId(allTagIds).stream()
                .collect(Collectors.toMap(PmsProductEvaluationTags::getId,
                        PmsProductEvaluationTags::getTagsName));
      return new AsyncResult<>(tagNameMap);
    }

    /**
     * 获取评论列表
     * @param productId 商品ID
     * @param commentInfos 评论列表
     * @return Future对象
     */
    @NotNull
    @Async("commentListThreadPool")
    Future<List<CommentInfo>> getCommentInfos(Long productId, List<CommentInfo> commentInfos) {
        // 根据商品ID查询SKU信息并封装成Map
        Map<Long, String> skuMap = pmsSkuStockMapper.findByProductIdList(productId).stream()
                .collect(Collectors.toMap(PmsSkuStock::getId, PmsSkuStock::getSpData));

        // 过滤与SKU相关的评论
        List<CommentInfo> filteredCommentInfos = commentInfos.stream()
                .filter(commentInfo -> commentInfo != null && skuMap.containsKey(commentInfo.getSkuId()))
                .map(commentInfo -> {
                    CommentInfo info = new CommentInfo();
                    info.setId(commentInfo.getId());
                    info.setCreateTime(commentInfo.getCreateTime());
                    info.setContent(commentInfo.getContent());
                    info.setCreateBy(commentInfo.getCreateBy());
                    info.setSkuValue(skuMap.get(commentInfo.getSkuId()));
                    return info;
                })
                .collect(Collectors.toList());
        return new AsyncResult<>(filteredCommentInfos);
    }

}
